import moment from 'moment'

import type { CheckboxValueType } from 'element-plus'

import { getCarQueue, updateLoadingCarRequest, getLOutletList, updateCarQueueRequest, cancelCarQueueRequest } from '@/api/signboard/index'
import type { CarQueryParams, QueueVehicle, MoveType } from '@/api/signboard/index'

import { useRequest } from '@/hooks/useRequest'

import { getProcessingOrderData } from '@/api/order/index'
import type { SearchParams, OrderDetail, SendVehicle, ReturnVehicle, Vehicle } from '@/api/order/index'

export type VehicleRow = QueueVehicle & { checked?: boolean }
/**
 * 左侧车辆队列
 * @param queueSearchParams 请求参数
 * @param cycle 是否自动刷新，方便调试
 */
export function useCarQueue(queueSearchParams, cycle = true) {
  let timer = null

  const clearTimer = () => {
    timer && clearInterval(timer)
    timer = null
  }

  const tableData = ref<VehicleRow[]>([])
  // 单选选中值
  let prevSelection: VehicleRow | null = null

  const { run, runAsync, loading } = useRequest(getCarQueue, {
    manual: true,
    onSuccess({ result }) {
      let rowIndex = -1 // 查找原有选中 index
      tableData.value = result.map((row, index) => {
        const temp = {
          ...row,
          checked: false
        }
        if (prevSelection && prevSelection.id === row.id && prevSelection.checked) {
          temp.checked = true
          rowIndex = index // 上次操作车辆还在队列，修改引用
        }
        return temp
      })
      // 修改引用对象，ref 会转换对象下一层
      // 通过 index 索引到的数据仍有响应式
      // 直接遍历保存数据没有响应式
      prevSelection = rowIndex < 0 ? null : tableData.value[rowIndex]
      if (timer !== null) {
        clearTimer()
      }
      if (!cycle) {
        return
      }
      timer = setInterval(() => {
        refreshInterval()
      }, 60 * 1000)
    }
  })

  timer = setInterval(() => {
    refreshInterval()
  }, 60 * 1000)

  onUnmounted(() => {
    clearTimer()
  })

  // 刷新定时器，没有分页，直接请求刷新数据
  const refreshInterval = () => {
    if (!queueSearchParams.mixingStationCode) {
      return
    }
    run(queueSearchParams)
  }

  // 搜索车辆队列
  const handleSearchCar = () => {
    if (!queueSearchParams.mixingStationCode) {
      ElMessage.error('请选择搅拌站')
      return
    }
    return runAsync(queueSearchParams)
  }

  const handleStatusClick = (status: 1 | 2) => {
    if (status === queueSearchParams.status) return
    queueSearchParams.status = status
    handleSearchCar()
  }

  const handleTableSelect = (val: CheckboxValueType, row: VehicleRow) => {
    // 已选中清空选中
    prevSelection && (prevSelection.checked = false)
    // 默认未选中
    prevSelection = null
    if (val) {
      prevSelection = row
    }
  }
  // 提交中，禁止操作
  const moveFreezing = ref(false)
  const handleMoveClick = (type: MoveType) => {
    if (!prevSelection) {
      // ElMessage.error('请选择操作车辆')
      return
    }
    moveFreezing.value = true
    const last = Date.now()
    updateCarQueueRequest({ id: prevSelection.id, order: type })
      .then(async () => {
        // ElMessage.success('操作成功')
        await handleSearchCar()
        const done = Date.now()
        // 点击事件触发，到请求响应后
        // 最小 500 ms 触发间隔
        // 如果列表刷新响应已过 500 ms
        // 直接修改
        const remain = Math.max(last + 500 - done, 0)
        setTimeout(() => {
          moveFreezing.value = false
        }, remain)
      })
      .catch(() => {
        moveFreezing.value = false
      })
  }

  const handleCancel = () => {
    if (!prevSelection) {
      return
    }

    ElMessageBox.confirm('是否取消排队', '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    }).then(async () => {
      moveFreezing.value = true
      const last = Date.now()
      try {
        await cancelCarQueueRequest({ id: prevSelection.id })
        ElMessage.success('取消排队操作成功')
        await handleSearchCar()
        const done = Date.now()
        // 点击事件触发，到请求响应后
        // 最小 500 ms 触发间隔
        // 如果列表刷新响应已过 500 ms
        // 直接修改
        const remain = Math.max(last + 500 - done, 0)
        setTimeout(() => {
          moveFreezing.value = false
        }, remain)
      } finally {
        moveFreezing.value = false
      }
    })
  }

  return {
    tableData,
    handleSearchCar,
    loading,
    handleStatusClick,
    handleTableSelect,
    moveFreezing,
    handleMoveClick,
    handleCancel
  }
}

// 编辑功能
export function useEdit(queryParams, cb: () => void) {
  const editDialogVisible = ref(false)
  const editFormRef = ref()
  const editFormModel = reactive({
    id: '',
    carNumber: '', // 顶替的车牌号
    outlet: null // 装料口
  })
  const editFormRules = {
    carNumber: [{ required: true, message: '请选择装货车辆', trigger: 'change' }],
    outlet: [{ required: true, message: '请输入装料口', trigger: 'blur' }]
  }

  const outletList = ref([]) // 装料口数组
  const editableVehicles = ref([])
  // 可选择车辆列表，排队中所有车辆
  const editLoading = ref(false)
  const handleEdit = (row: VehicleRow) => {
    editFormModel.id = row.id
    editFormModel.carNumber = row.carNumber
    editFormModel.outlet = row.outlet
    editableVehicles.value = [row]
    getStationOutletList()
    getCarQueue({
      ...queryParams,
      status: 1
    })
      .then(({ result }) => {
        editableVehicles.value = editableVehicles.value.concat(result)
      })
      .catch(() => {
        ElMessage.error('获取装货车辆失败')
      })
    editDialogVisible.value = true
  }

  const getStationOutletList = async () => {
    const { result } = await getLOutletList({
      mixingStationCode: queryParams.mixingStationCode
    })
    outletList.value = result
  }

  const handleEditCommitClick = () => {
    editFormRef.value?.validate((valid: boolean) => {
      if (valid) {
        editLoading.value = true
        updateLoadingCarRequest(editFormModel)
          .then(() => {
            ElMessage.success('编辑成功')
            editDialogVisible.value = false
            cb()
          })
          .finally(() => {
            editLoading.value = false
          })
      }
    })
  }

  return {
    editDialogVisible,
    editFormRef,
    editFormModel,
    editFormRules,
    editableVehicles,
    editLoading,
    outletList,
    handleEdit,
    handleEditCommitClick
  }
}

/**
 * 右侧订单功能
 * @param queueSearchParams 请求参数
 * @param cycle 是否自动刷新，方便调试
 */
export function useOrder(stationState: CarQueryParams, cycle = true) {
  let timer = null
  const orderQueryFormRef = ref(ElForm)
  const orderQueryParams = reactive<Partial<SearchParams>>({ timeType: 1, nowPage: 1, pageSize: 10 })
  const total = ref(0)
  const orderTableData = ref<OrderDetail[]>([])

  const clearTimer = () => {
    timer && clearInterval(timer)
    timer = null
  }

  // 列表请求，自动执行第一次
  const { run, loading: orderTableLoading } = useRequest(getProcessingOrderData, {
    manual: true,
    onSuccess({ result }) {
      const { records, total: totalRes } = result
      total.value = totalRes
      orderTableData.value = orderTableData.value.concat(tableMapper(records))
      if (timer !== null) {
        clearTimer()
      }
      if (!cycle) {
        return
      }
      timer = setInterval(() => {
        refreshInterval()
      }, 60 * 1000)
    }
  })

  timer = setInterval(() => {
    refreshInterval()
  }, 60 * 1000)

  onUnmounted(() => {
    clearTimer()
  })
  // 刷新操作
  const refreshInterval = () => {
    if (!stationState.mixingStationCode) {
      return
    }
    // 有分页，需要重置到第一页
    orderQueryParams.nowPage = 1
    orderTableData.value = []
    run({ ...orderQueryParams, mixingStationCode: stationState.mixingStationCode })
  }

  // 点击查询操作
  const handleOrderQuery = () => {
    if (!stationState.mixingStationCode) {
      ElMessage.error('请选择搅拌站')
      return
    }
    // 需要重置为查询首页
    orderQueryParams.nowPage = 1
    orderTableData.value = []
    // 强制请求
    run({ ...orderQueryParams, mixingStationCode: stationState.mixingStationCode })
  }
  const handleRest = () => {
    orderQueryFormRef.value.resetFields()
    // handleOrderQuery()
  }
  // 全部加载完成禁止 loading
  const isDone = computed(() => orderTableData.value.length >= total.value)
  // 滚动加载
  const onloadData = () => {
    // 达到最大值需要停止加载
    if (isDone.value || orderTableLoading.value) return
    // 请求下一页
    orderQueryParams.nowPage += 1
    run({ ...orderQueryParams, mixingStationCode: stationState.mixingStationCode })
  }
  function tableMapper(records: OrderDetail[]) {
    return records.map(row => {
      // 转换车辆列表
      row.enhanceOutBoundCarList = row.outBoundCarList ? formatSendCar(row.outBoundCarList, row.averageDeliveryMin) : []
      row.enhanceReturnCarList = row.returnCarList ? formatReturnCar(row.returnCarList, row.averageReturnTripMin) : []
      return row
    })
  }

  /**
   * 计算车辆运输进度
   * @param carList 车辆信息
   * @param estimate 预估运输时长，可能没有
   */
  function formatSendCar(carList: SendVehicle[], estimate?: string): Required<SendVehicle>[] {
    const estimateToNumber = +estimate
    return carList.map(car => {
      const { leaveTime } = car
      let progress = -1
      if (estimateToNumber) {
        const usedTime = moment().diff(moment(leaveTime))
        const usedTimeToMins = usedTime / 1000 / 60
        progress = usedTimeToMins >= estimateToNumber ? 100 : Math.floor((usedTimeToMins / estimateToNumber) * 100)
      }

      return {
        ...car,
        arriveTime: estimateToNumber ? moment(leaveTime).add(estimateToNumber, 'm').format('YYYY-MM-DD HH:mm:ss') : '-',
        progress
      }
    })
  }

  /**
   * 计算车辆运输进度
   * @param carList 车辆信息
   * @param estimate 预估运输时长，可能没有
   */
  function formatReturnCar(carList: ReturnVehicle[], estimate?: string): Required<ReturnVehicle>[] {
    const estimateToNumber = +estimate
    return carList.map(car => {
      // 返程存在有预估到达时长，但是车辆还没开始返程情况
      // 也就是 unloadEndTime 不存在
      const { unloadEndTime } = car
      let progress = -1
      if (estimateToNumber) {
        // 没有 unloadEndTime，还未开始返程，进度 0
        const usedTime = unloadEndTime ? moment().diff(moment(unloadEndTime)) : 0
        const usedTimeToMins = usedTime / 1000 / 60
        progress = usedTimeToMins >= estimateToNumber ? 100 : Math.floor((usedTimeToMins / estimateToNumber) * 100)
      }

      return {
        ...car,
        arriveTime: estimateToNumber ? moment(unloadEndTime).add(estimateToNumber, 'm').format('YYYY-MM-DD HH:mm:ss') : '-',
        progress
      }
    })
  }

  const expDialogVisible = ref(false)
  const expWaybillId = ref('')
  // 点击车辆，异常打开运单弹框
  const handleCarClick = (car: Vehicle) => {
    expWaybillId.value = car.id
    expDialogVisible.value = true
  }

  function progressCarStyle(car: SendVehicle | ReturnVehicle, isReverse = false) {
    if (car.progress < 0) return ''

    return `position:absolute;${isReverse ? 'right' : 'left'}: ${car.progress}%;transform: translateX(${isReverse ? '100' : '-100'}%);`
  }

  return {
    orderQueryFormRef,
    orderQueryParams,
    orderTableLoading,
    orderTableData,
    isDone,
    handleOrderQuery,
    handleRest,
    onloadData,
    expDialogVisible,
    expWaybillId,
    handleCarClick,
    progressCarStyle
  }
}
